home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / Dots & Pixels / sources / gworld.cp < prev    next >
Text File  |  1995-09-29  |  8KB  |  236 lines

  1. #include <stdlib.h>
  2.  
  3. #include <Windows.h>
  4. #include <QDOffscreen.h>
  5. #include <Memory.h>
  6. #include <Fonts.h>
  7. #include <Packages.h>
  8. #include <SegLoad.h>
  9. #include <ToolUtils.h>
  10. #include <TextEdit.h>
  11. #include <Files.h>
  12.  
  13. #include "C_randomizer.h"
  14.  
  15. #include "general.h"
  16. #include "port.h"
  17. #include "gworld.h"
  18.  
  19. const unsigned short gworld::extensions[ 256] =
  20. {
  21.     0x0000, 0x0003, 0x000C, 0x000F, 0x0030, 0x0033, 0x003C, 0x003F,
  22.     0x00C0, 0x00C3, 0x00CC, 0x00CF, 0x00F0, 0x00F3, 0x00FC, 0x00FF,
  23.     0x0300, 0x0303, 0x030C, 0x030F, 0x0330, 0x0333, 0x033C, 0x033F,
  24.     0x03C0, 0x03C3, 0x03CC, 0x03CF, 0x03F0, 0x03F3, 0x03FC, 0x03FF,
  25.     0x0C00, 0x0C03, 0x0C0C, 0x0C0F, 0x0C30, 0x0C33, 0x0C3C, 0x0C3F,
  26.     0x0CC0, 0x0CC3, 0x0CCC, 0x0CCF, 0x0CF0, 0x0CF3, 0x0CFC, 0x0CFF,
  27.     0x0F00, 0x0F03, 0x0F0C, 0x0F0F, 0x0F30, 0x0F33, 0x0F3C, 0x0F3F,
  28.     0x0FC0, 0x0FC3, 0x0FCC, 0x0FCF, 0x0FF0, 0x0FF3, 0x0FFC, 0x0FFF,
  29.     0x3000, 0x3003, 0x300C, 0x300F, 0x3030, 0x3033, 0x303C, 0x303F,
  30.     0x30C0, 0x30C3, 0x30CC, 0x30CF, 0x30F0, 0x30F3, 0x30FC, 0x30FF,
  31.     0x3300, 0x3303, 0x330C, 0x330F, 0x3330, 0x3333, 0x333C, 0x333F,
  32.     0x33C0, 0x33C3, 0x33CC, 0x33CF, 0x33F0, 0x33F3, 0x33FC, 0x33FF,
  33.     0x3C00, 0x3C03, 0x3C0C, 0x3C0F, 0x3C30, 0x3C33, 0x3C3C, 0x3C3F,
  34.     0x3CC0, 0x3CC3, 0x3CCC, 0x3CCF, 0x3CF0, 0x3CF3, 0x3CFC, 0x3CFF,
  35.     0x3F00, 0x3F03, 0x3F0C, 0x3F0F, 0x3F30, 0x3F33, 0x3F3C, 0x3F3F,
  36.     0x3FC0, 0x3FC3, 0x3FCC, 0x3FCF, 0x3FF0, 0x3FF3, 0x3FFC, 0x3FFF,
  37.     0xC000, 0xC003, 0xC00C, 0xC00F, 0xC030, 0xC033, 0xC03C, 0xC03F,
  38.     0xC0C0, 0xC0C3, 0xC0CC, 0xC0CF, 0xC0F0, 0xC0F3, 0xC0FC, 0xC0FF,
  39.     0xC300, 0xC303, 0xC30C, 0xC30F, 0xC330, 0xC333, 0xC33C, 0xC33F,
  40.     0xC3C0, 0xC3C3, 0xC3CC, 0xC3CF, 0xC3F0, 0xC3F3, 0xC3FC, 0xC3FF,
  41.     0xCC00, 0xCC03, 0xCC0C, 0xCC0F, 0xCC30, 0xCC33, 0xCC3C, 0xCC3F,
  42.     0xCCC0, 0xCCC3, 0xCCCC, 0xCCCF, 0xCCF0, 0xCCF3, 0xCCFC, 0xCCFF,
  43.     0xCF00, 0xCF03, 0xCF0C, 0xCF0F, 0xCF30, 0xCF33, 0xCF3C, 0xCF3F,
  44.     0xCFC0, 0xCFC3, 0xCFCC, 0xCFCF, 0xCFF0, 0xCFF3, 0xCFFC, 0xCFFF,
  45.     0xF000, 0xF003, 0xF00C, 0xF00F, 0xF030, 0xF033, 0xF03C, 0xF03F,
  46.     0xF0C0, 0xF0C3, 0xF0CC, 0xF0CF, 0xF0F0, 0xF0F3, 0xF0FC, 0xF0FF,
  47.     0xF300, 0xF303, 0xF30C, 0xF30F, 0xF330, 0xF333, 0xF33C, 0xF33F,
  48.     0xF3C0, 0xF3C3, 0xF3CC, 0xF3CF, 0xF3F0, 0xF3F3, 0xF3FC, 0xF3FF,
  49.     0xFC00, 0xFC03, 0xFC0C, 0xFC0F, 0xFC30, 0xFC33, 0xFC3C, 0xFC3F,
  50.     0xFCC0, 0xFCC3, 0xFCCC, 0xFCCF, 0xFCF0, 0xFCF3, 0xFCFC, 0xFCFF,
  51.     0xFF00, 0xFF03, 0xFF0C, 0xFF0F, 0xFF30, 0xFF33, 0xFF3C, 0xFF3F,
  52.     0xFFC0, 0xFFC3, 0xFFCC, 0xFFCF, 0xFFF0, 0xFFF3, 0xFFFC, 0xFFFF
  53. };
  54.  
  55. gworld::gworld( int breedte, int hoogte, int diepte, port &original)
  56. {
  57.     if( (diepte != 1) && (diepte !=  2) && (diepte !=  4)
  58.         && (diepte != 8) && (diepte != 16) && (diepte != 32))
  59.     {
  60.         DebugStr( "\pgworld::gworld: illegal depth passed");
  61.         exit( EXIT_FAILURE);
  62.     }
  63.     if( (hoogte <= 0) || (breedte <= 0))
  64.     {
  65.         DebugStr( "\pgworld::gworld: illegal width and/or height passed");
  66.         exit( EXIT_FAILURE);
  67.     }
  68.     myRect.top    = 0;
  69.     myRect.left   = 0;
  70.     myRect.bottom = hoogte;
  71.     myRect.right  = breedte;
  72.     
  73.     de_diepte     = diepte;
  74.     
  75.     if( NewGWorld( &myGWorldPtr, de_diepte, &myRect, nil, original.getGDevice(), noNewDevice) != noErr)
  76.     {
  77.         //
  78.         // retry in temporary memory. We do not set the 'AllowPurgePixels' bit.
  79.         // This is not the proper thing to do, but doing it this way is better than
  80.         // failing immediately.
  81.         //
  82.         CheckForError( NewGWorld(
  83.                 &myGWorldPtr, de_diepte, &myRect, nil, original.getGDevice(), noNewDevice | useTempMem), "NewGWorld");
  84.     }
  85.     myGDHandle = GetGWorldDevice( myGWorldPtr);
  86.     
  87.     const PixMapHandle myPixMapH = GetGWorldPixMap( myGWorldPtr);
  88.  
  89.     CheckForError( !LockPixels( myPixMapH), "LockPixels");
  90.  
  91.     HLock( (Handle)myPixMapH); 
  92.         
  93.     myPix = (*myPixMapH);
  94. }
  95.  
  96. gworld::gworld( int breedte, int hoogte, int diepte, CTabHandle cTable)
  97. {
  98.     if( (diepte != 1) && (diepte !=  2) && (diepte !=  4)
  99.         && (diepte != 8) && (diepte != 16) && (diepte != 32))
  100.     {
  101.         DebugStr( "\pgworld::gworld: illegal depth passed");
  102.         exit( EXIT_FAILURE);
  103.     }
  104.     if( (hoogte <= 0) || (breedte <= 0))
  105.     {
  106.         DebugStr( "\pgworld::gworld: illegal width and/or height passed");
  107.         exit( EXIT_FAILURE);
  108.     }
  109.     myRect.top    = 0;
  110.     myRect.left   = 0;
  111.     myRect.bottom = hoogte;
  112.     myRect.right  = breedte;
  113.     
  114.     de_diepte     = diepte;
  115.     
  116.     if( NewGWorld( &myGWorldPtr, de_diepte, &myRect, cTable, nil, 0) != noErr)
  117.     {
  118.         //
  119.         // retry in temporary memory. We do not set the 'AllowPurgePixels' bit.
  120.         // This is not the proper thing to do, but doing it this way is better than
  121.         // failing immediately.
  122.         //
  123.         CheckForError( NewGWorld(
  124.                 &myGWorldPtr, de_diepte, &myRect, cTable, nil, useTempMem), "NewGWorld");
  125.     }
  126.     myGDHandle = GetGWorldDevice( myGWorldPtr);
  127.     
  128.     const PixMapHandle myPixMapH = GetGWorldPixMap( myGWorldPtr);
  129.  
  130.     CheckForError( !LockPixels( myPixMapH), "LockPixels");
  131.  
  132.     HLock( (Handle)myPixMapH); 
  133.         
  134.     myPix = (*myPixMapH);
  135. }
  136.  
  137. gworld::~gworld()
  138. {
  139.     const PixMapHandle myPixMapH = GetGWorldPixMap( myGWorldPtr);
  140.     HUnlock( (Handle)myPixMapH);
  141.     UnlockPixels( myPixMapH);
  142.     DisposeGWorld( myGWorldPtr);
  143. }
  144.  
  145. void gworld::fill_random() const
  146. {
  147.     //
  148.     // Note: this could be done faster since randomizer_step() returns an
  149.     // unsigned long. However, this would take some extra code since we can
  150.     // not be sure that rowBytes is a multiple of four.
  151.     // Random probably is even slower, but we could do a GetTrapAdress to
  152.     // prevent trap overhead.
  153.     // 941101: Now doing it the faster way. This could have been done all
  154.     // along. Since a pixmap is contiguous in memory we only have to take a
  155.     // pad word into account at the end of the pixmap data.
  156.     // => only one loop needed.
  157.     //
  158.     const int rowChars  = myPix->rowBytes & 0x2FFF;
  159.     const int numRows   = myPix->bounds.bottom - myPix->bounds.top;
  160.     const int totalChars = rowChars * numRows;    // always even, rowChars is even
  161.     const int totalLongs = totalChars / 4;
  162.  
  163.     const int pad_them  = (totalChars & 2) != 0;
  164.  
  165.     unsigned long *curAddress = (unsigned long *)myPix->baseAddr; // pray it to be even ;->
  166.     
  167.     randomizer_fill( curAddress, totalLongs);
  168.  
  169.     if( pad_them)
  170.     {
  171.         unsigned short *curAddresToo = (unsigned short *)(curAddress + totalLongs);
  172.         *curAddresToo = randomizer_step();
  173.     }
  174. }
  175.  
  176. void gworld::two_bit_merge( const gworld &left, const gworld &right) const
  177. {
  178.     if( (de_diepte != 2) || (left.de_diepte != 1) || (right.de_diepte != 1))
  179.     {
  180.         DebugStr( "\pgworld::two_bit_merge: depths not 2, 1, and 1");
  181.         exit( EXIT_FAILURE);
  182.     }
  183.     const int left_rowBytes  = left.myPix->rowBytes & 0x2FFF;
  184.     const int right_rowBytes = right.myPix->rowBytes & 0x2FFF;
  185.     const int rowWords = (myPix->rowBytes & 0x2FFF) / 2; // always even => division is safe
  186.     //
  187.     // Note: contrary to what one would expect one does not have to have
  188.     // 'rowWords == left_rowBytes' when both worlds are of equal width,
  189.     // and have depths 1 and 2. Two GWorlds of (equal) depth one do have
  190.     // equal values of rowBytes, though.
  191.     //
  192.     if( (left_rowBytes != right_rowBytes) || (rowWords > left_rowBytes))
  193.     {
  194.         DebugStr( "\pgworld::two_bit_merge: rowBytes and/or rowWords don't match");
  195.         exit( EXIT_FAILURE);
  196.     }
  197.     const int numRows = myPix->bounds.bottom - myPix->bounds.top;
  198.  
  199.     unsigned short *curAddress  = (unsigned short *)myPix->baseAddr;
  200.     unsigned char *leftAddress  = (unsigned  char *)left.myPix->baseAddr;
  201.     unsigned char *rightAddress = (unsigned  char *)right.myPix->baseAddr;
  202.  
  203.     for( int row = 0; row < numRows; row++)
  204.     {
  205.         unsigned char *leftRow  = leftAddress;
  206.         unsigned char *rightRow = rightAddress;
  207.  
  208.         for( int wordNo = 0; wordNo < rowWords; wordNo++)
  209.         {
  210.             const unsigned short left_extended  = extendChar( *leftRow++);
  211.             const unsigned short right_extended = extendChar( *rightRow++);
  212.             *curAddress++ = (left_extended & 0xAAAA) | (right_extended & 0x5555);
  213.         }
  214.         leftAddress  += left_rowBytes;
  215.         rightAddress += right_rowBytes;
  216.     }
  217. }
  218.  
  219. OSErr gworld::dump( short defile) const
  220. {
  221.     const int rowChars = (myPix->rowBytes & 0x2FFF);
  222.     const int numRows   = myPix->bounds.bottom - myPix->bounds.top;
  223.     long totalChars = rowChars * numRows;
  224.     const void *curAddress = (const void *)myPix->baseAddr;
  225.     return FSWrite( defile, &totalChars, curAddress);
  226. }
  227.  
  228. OSErr gworld::load( short defile) const
  229. {
  230.     const int rowChars = (myPix->rowBytes & 0x2FFF);
  231.     const int numRows   = myPix->bounds.bottom - myPix->bounds.top;
  232.     long totalChars = rowChars * numRows;
  233.     void *curAddress = (void *)myPix->baseAddr;
  234.     return FSRead( defile, &totalChars, curAddress);
  235. }
  236.